package cn.tpshion.devops.service.impl;

import cn.tpshion.devops.common.enums.NodeType;
import cn.tpshion.devops.common.CoreException;
import cn.tpshion.devops.common.constant.RedisKey;
import cn.tpshion.devops.domain.dto.TaskWorkDTO;
import cn.tpshion.devops.domain.entity.GitSecretData;
import cn.tpshion.devops.domain.entity.NodeData;
import cn.tpshion.devops.domain.entity.SecretData;
import cn.tpshion.devops.domain.entity.TaskWork;
import cn.tpshion.devops.handle.GitHandle;
import cn.tpshion.devops.node.data.GitData;
import cn.tpshion.devops.service.TaskService;
import cn.tpshion.devops.util.AssertUtil;
import cn.tpshion.devops.util.IdUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TaskServiceImpl implements TaskService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private GitHandle gitHandle;

    @Value("${node.workspace}")
    private String workspace;

    @Override
    public TaskWork saveFlowData(TaskWork taskWork) {
        if(StringUtils.isBlank(taskWork.getTaskId())){
            taskWork.setTaskId(IdUtil.makeId());
            taskWork.setCreateTime(System.currentTimeMillis());
        }

        // 检查工作空间是否存在
        File file = new File(workspace + File.separator + taskWork.getTaskId());
        if(!file.isDirectory() || !file.exists()){
            // 创建工作空间
            AssertUtil.isFalse(file.mkdirs(), "创建工作空间失败");
        }

        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        hash.put(RedisKey.TASK_KEY, taskWork.getTaskId(), JSON.toJSONString(taskWork));
        return taskWork;
    }

    @Override
    public TaskWork getFlowData(TaskWorkDTO dto) {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        String taskWork = hash.get(RedisKey.TASK_KEY, dto.getTaskId());
        return JSON.parseObject(taskWork, TaskWork.class);
    }

    @Override
    public List<TaskWork> getFlowList() {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        Map<String, String> workMap = hash.entries(RedisKey.TASK_KEY);
        if(ObjectUtils.isEmpty(workMap)){
            return null;
        }

        return workMap.values().stream()
                .map(i -> JSON.parseObject(i, TaskWork.class))
                .sorted(Comparator.comparing(TaskWork::getCreateTime))
                .collect(Collectors.toList());
    }

    @Override
    public List<String> branchList(TaskWorkDTO dto) {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        String value = hash.get(RedisKey.TASK_KEY, dto.getTaskId());
        AssertUtil.isTrue(StringUtils.isBlank(value), "数据错误");

        TaskWork taskWork = JSON.parseObject(value, TaskWork.class);
        AssertUtil.isTrue(Objects.isNull(taskWork) || ObjectUtils.isEmpty(taskWork.getNodeDataList()), "数据错误");

        Optional<NodeData> optional = taskWork.getNodeDataList().stream().filter(i -> i.getType().equals(NodeType.GIT.getType())).findFirst();
        AssertUtil.isTrue(!optional.isPresent(), "数据错误，没有git节点");

        NodeData nodeData = optional.get();
        GitData gitData = JSON.parseObject(JSON.toJSONString(nodeData.getData()), GitData.class);

        GitSecretData gitSecret = getGitSecret(gitData.getSecretName());
        AssertUtil.isTrue(Objects.isNull(gitSecret), "获取git密钥失败");

        gitData.setUsername(gitSecret.getUsername());
        gitData.setPassword(gitSecret.getPassword());

        try {
            return gitHandle.getBranchList(gitData, dto.getTaskId());
        } catch (Exception e) {
            log.error("branchList error:{}", e.getMessage(), e);
        }
        return null;
    }

    private GitSecretData getGitSecret(String secretName){
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        String value = hash.get(RedisKey.SECRET, secretName);
        SecretData secretData = JSON.parseObject(value, SecretData.class);
        return JSON.parseObject(JSON.toJSONString(secretData.getData()), GitSecretData.class);
    }

    @Override
    public void deleteFlow(TaskWorkDTO dto) {
        File file = new File(workspace + File.separator + dto.getTaskId());
        if(file.isDirectory() && file.exists()){
            // 删除工作空间
            try {
                FileUtils.deleteDirectory(file);
            } catch (IOException e) {
                log.error("deleteFlow error:{}", e.getMessage(), e);
                throw new CoreException("删除工作空间失败");
            }
        }

        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        hash.delete(RedisKey.TASK_KEY, dto.getTaskId());
    }
}
